//延时防抖（在一定时间内只执行最后一次操作）函数需要频繁触发情况时，只有足够空闲的时间，才执行一次
//应用场景：实时搜索（keyup）、拖拽（mousemove）、窗口调整(resize)
export function debounce(callback, delay) {
	let timeout
	return function(...args) {
		clearTimeout(timeout) //所有频繁的操作都会被清空，只有最后一次的不会清空
		timeout = setTimeout(() => {
			callback.apply(this, args)
		}, delay)
	}
}

/* 完美节流实现-ts */
/* 
双保险机制

通过时间戳 (lastTime=0) 确保周期内首次触发立即执行 
 */
/**
 * 节流
 * @param handler 待节流的函数
 * @param wait 节流时间间隔（毫秒）
 * @returns 节流处理后的函数
 */
export const throttle = (
	handler: (...args: any[]) => void,
	wait: number = 300
): Function => {
	let lastTime: number = 0;

	return function(this: any, ...args: any[]) {
		const now = Date.now();

		// 立即执行条件：首次调用或超过等待时间
		if (now - lastTime >= wait) {
			handler.apply(this, args);
			lastTime = now;
		}
	};
};
/* 使用示例 */
const throttledFn = throttle((text: string) => {
	console.log("执行:", text);
}, 500);

// 高频调用
throttledFn("A"); // 立即执行
throttledFn("B"); // 被节流（500ms内）
setTimeout(() => throttledFn("C"), 600); // 超过间隔，再次立即执行

// ========================================================================


/* 使用 */
// 处理函数
// function handle() {
//     console.log(Math.random());
// }
// // 滚动事件
// window.addEventListener('scroll', debounce(handle,500));

//节流:预定一个函数只有在大于等于执行周期时才执行，周期内调用不执行。好像水滴攒到一定重量才会落下。
//应用场景：窗口调整(resize)、页面滚动(scroll)、抢购疯狂点击(mousedowm)
// 用时间戳实现
export function throttle(handler, delay) {
	let lastTime = Date.now();
	return function() {
		let nowTime = Date.now();
		if (nowTime - lastTime > delay) {
			handler.apply(this, arguments);
			lastTime = nowTime;
		}
	}
}

//节流用定时器实现代码：
export function throttle(fn, delay) {
	let canRun = true; // 通过闭包保存一个标记
	return function() {
		// 在函数开头判断标记是否为true，不为true则return
		if (!canRun) return;
		// 立即设置为false
		canRun = false;
		// 将外部传入的函数的执行放在setTimeout中
		setTimeout(() => {
			// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
			// 当定时器没有执行的时候标记永远是false，在开头被return掉
			fn.apply(this, arguments);
			canRun = true;
		}, delay);
	};
}

/* 使用 */
// function sayHi(e) {
//     console.log(e.target.innerWidth, e.target.innerHeight);
// }
// window.addEventListener('resize', throttle(sayHi,500));

//监听DOM样式变化（配置项中attributeFilter只配置了样式）
//应用场景:某个样式需要根据一个dom元素的样式变化而相应改变
export function observerDomRestyle(dom, callback) { //兼容IE11
	const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
	const observer = new MutationObserver(callback)
	observer.observe(dom, {
		attributes: true,
		attributeFilter: ['style'],
		attributeOldValue: true
	}) //attributeFilter只监听样式style属性的变化
	return observer //返回observer对象以便使用observer.takeRecords()获取监听列表（清空监听列表）、observer.disconnect()断开监听，详查MutationObserver对象
}